//------------------------------------------------------------
//  Filename: b200_fc16_amp.v
//   
//  Author  : wlduan@gmail.com
//  Revise  : 2024-04-11 19:10
//  Description: 
//   
//  Copyright (C) 2021, UCCHIP, Inc. 					      
//  All Rights Reserved.                                       
//-------------------------------------------------------------
//
`timescale 1ns/1ps
 
module b200_fc16_amp ( 
    input  bus_clk,
    input  bus_rst,

    input  [63:0] tx_tdata, input  tx_tlast, input  tx_tvalid, output tx_tready,
    output [63:0] rx_tdata, output rx_tlast, output rx_tvalid, input  rx_tready,

    output dbg_2m_sout
);      

///////////////////////////////////////////////////////////////////////
reg eof;

always @(posedge bus_clk, posedge bus_rst) begin
  if(bus_rst) begin
    eof <= 1'b0;
  end
  else if(tx_tvalid&tx_tready)begin
    eof <= tx_tlast;
  end
end

wire sof;

assign sof = tx_tvalid & tx_tready & eof;

reg data_frm;
reg data_time_flg;

always @(posedge bus_clk, posedge bus_rst) begin
  if(bus_rst) begin
    data_frm <= 1'b0;
  end
  else if(sof) begin
    data_frm <= (tx_tdata[63:62] == 2'b00) ? 1'b1 : 1'b0;
  end
  else if( tx_tvalid & tx_tready )  begin
    data_frm <= 1'b0;
  end
end

always @(posedge bus_clk, posedge bus_rst) begin
  if(bus_rst) begin
    data_time_flg <= 1'b0;
  end
  else if(sof) begin
    data_time_flg <= (tx_tdata[63:61] == 3'b001) ? 1'b1 : 1'b0;
  end
  else if(tx_tlast) begin
    data_time_flg <= 1'b0;
  end
end

reg data_payload;

always @(posedge bus_clk, posedge bus_rst) begin
  if(bus_rst) begin
    data_payload <= 1'b0;
  end
  else if(data_frm) begin
    data_payload <= 1'b1;
  end
  else if(tx_tlast) begin
    data_payload <= 1'b0;
  end
end

assign covt_en = data_time_flg ? data_payload : (data_frm | data_payload);
///////////////////////////////////////////////////////////////////////
wire signed [14:0] i0, i1;
wire signed [14:0] q0, q1;
     
wire signed [14:0] abs_i0, abs_i1;
wire signed [14:0] abs_q0, abs_q1;
     
wire signed [14:0] max0, max1;
wire signed [14:0] min0, min1;
     
wire signed [15:0] mag0, mag1;

reg         [1:0]  mag_data;
reg                mag_data_vld;
wire               mag_data_rdy;
///////////////////////////////////////////////////////////////////////
assign i0       = tx_tdata[31:17]  ;
assign q0       = tx_tdata[15:1]   ;

assign abs_i0   = i0[14] ? (~i0+1) : i0;
assign abs_q0   = q0[14] ? (~q0+1) : q0;

assign max0     = abs_i0 > abs_q0 ? abs_i0 : abs_q0;
assign min0     = abs_i0 > abs_q0 ? abs_q0 : abs_i0;

assign mag0     = max0 + (min0 >> 2);
///////////////////////////////////////////////////////////////////////
assign i1       = tx_tdata[63:49]  ;
assign q1       = tx_tdata[47:33]  ;

assign abs_i1   = i1[14] ? (~i1+1) : i1;
assign abs_q1   = q1[14] ? (~q1+1) : q1;

assign max1     = abs_i1 > abs_q1 ? abs_i1 : abs_q1;
assign min1     = abs_i1 > abs_q1 ? abs_q1 : abs_i1;

assign mag1     = max1 + (min1 >> 2);
///////////////////////////////////////////////////////////////////////
wire [15:0] thresh_hold = 16'd25;

always @(posedge bus_clk, posedge bus_rst) begin
  if(bus_rst) begin
    mag_data     <= 2'b0;
    mag_data_vld <= 1'b0;
  end
  else begin
    mag_data[0] <= (mag0 > thresh_hold);
    mag_data[1] <= (mag1 > thresh_hold);
    mag_data_vld <= covt_en;
  end
end

///////////////////////////////////////////////////////////////////////
reg[7:0] cntr_div;

always @(posedge bus_clk, posedge bus_rst) begin
  if(bus_rst) begin
    cntr_div <= 8'b0;
  end
  else begin
    cntr_div <= (cntr_div < 49) ? (cntr_div + 1) : 8'b0 ;
  end
end

wire[1:0] mag_2m_sout;
wire      mag_2m_vld;
wire      mag_2m_rdy;

///////////////////////////////////////////////////////////////////////
reg mag_2m_bout;

always @(posedge bus_clk, posedge bus_rst) begin
  if(bus_rst) begin
    mag_2m_bout <= 1'b0;
  end
  else if(cntr_div == 50 ) begin
    mag_2m_bout <= mag_2m_sout[1];
  end
  else if(cntr_div == 99 ) begin
    mag_2m_bout <= mag_2m_sout[0];
  end
end

assign mag_2m_rdy  = (cntr_div == 99);
assign dbg_2m_sout = mag_2m_bout;
///////////////////////////////////////////////////////////////////////
axi_fifo #(
  .WIDTH    ( 2              ),       // Width of input/output data word
  .SIZE     ( 256            )        // log2 of the depth of the FIFO
) 
mag_fifo_inst0
(
  .clk      ( bus_clk         ),
  .reset    ( bus_rst         ),
  .clear    ( 1'b0            ),

  .i_tdata  ( mag_data        ),
  .i_tvalid ( mag_data_vld    ),
  .i_tready ( mag_data_rdy    ),

  .o_tdata  ( mag_2m_sout     ),
  .o_tvalid ( mag_2m_vld      ),
  .o_tready ( mag_2m_rdy      )
);

assign rx_tdata  = tx_tdata  ;
assign rx_tlast  = tx_tlast  ; 
assign rx_tvalid = tx_tvalid ; 
assign tx_tready = rx_tready ;

endmodule
